package com.ohuang.download_okhttp;

import com.ohuang.download.AbstractDownloadTask;
import com.ohuang.download.DownLoadClient;
import com.ohuang.download.DownLoadListener;
import com.ohuang.download.DownloadTask;
import com.ohuang.download.OhDownLoad;
import com.ohuang.download.PreDownLoadTask;
import com.ohuang.download.PreDownloadListener;
import com.ohuang.download.RemoteFile;
import com.ohuang.download.util.CloseableUtil;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.List;
import java.util.Map;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class OkDownloadClient extends DownLoadClient {

    OkHttpClient okHttpClient;

    public OkDownloadClient() {
        okHttpClient = new OkHttpClient();
    }

    public OkDownloadClient(OkHttpClient okHttpClient) {
        this.okHttpClient = okHttpClient;
    }

    @Override
    public AbstractDownloadTask createTask(OhDownLoad ohDownLoad, String url, File file, DownLoadListener downloadListener) {
        return new OkDownloadTask(ohDownLoad, url, file, downloadListener);
    }

    @Override
    public PreDownLoadTask createPreTask(OhDownLoad ohDownLoad, String url, PreDownloadListener preDownloadListener) {
        return new OkPreDownLoadTask(ohDownLoad, url, preDownloadListener);
    }


    private class OkPreDownLoadTask extends PreDownLoadTask {
        public OkPreDownLoadTask(OhDownLoad ohDownLoad, String url, PreDownloadListener preDownloadListener) {
            super(ohDownLoad, url, preDownloadListener);
        }

        @Override
        public void predownload(String url) {
            RemoteFile remoteFile = new RemoteFile(url);
            setRemoteFile(remoteFile);
            Request request = new Request.Builder().url(url)
                    .header("Range", "bytes=" + 0 + "-")
                    .build();
            try {
                Response response = okHttpClient.newCall(request)
                        .execute();

                Map<String, List<String>> stringListMap = response.headers().toMultimap();
                remoteFile.setAndDecodeHeaders(stringListMap);
                onSuccess();
            } catch (IOException e) {
                e.printStackTrace();
                setError(e);
            }
        }
    }


    private class OkDownloadTask extends AbstractDownloadTask {


        public OkDownloadTask(OhDownLoad ohDownLoad, String url, File file, DownLoadListener loadListener) {
            super(ohDownLoad, url, file, loadListener);
        }

        long total = 0;

        @Override
        public void download(String url, File file) {

            InputStream inputStream = null;
            RandomAccessFile randomAccessFile = null;
            try {
                if (!file.exists()) {
                    if (file.getParentFile() != null) {
                        file.getParentFile().mkdirs();
                    }
                    file.createNewFile();
                }
                randomAccessFile = new RandomAccessFile(file, "rw");
                long lastIndex = randomAccessFile.length();
                Request request = new Request.Builder().url(url)
                        .header("Range", "bytes=" + lastIndex + "-")
                        .build();
                long index = lastIndex;

                Response response = okHttpClient.newCall(request)
                        .execute();

                String contentRange = response.header("Content-Range");
                if (contentRange != null && contentRange.length() > 0) {
                    String[] strings = contentRange.split("/");
                    if (strings.length > 1) {
                        String string = strings[1];
                        try {
                            total = Long.parseLong(string);
                        } catch (Exception e) {

                        }
                    }
                }
                inputStream = response.body().byteStream();
                byte[] bytes = new byte[1024];
                int i = 0;
                if (response.code() == 200 || response.code() == 206) {
                    if (response.code() == 200) { //不支持断点
                        index = 0;
                    }
                    randomAccessFile.seek(index);
                    while ((i = inputStream.read(bytes, 0, 1024)) != -1 && getRunSate() == DownloadTask.SATE_RUN) {
                        randomAccessFile.write(bytes, 0, i);
                        index += i;
                        onProgress(index, total);
                    }

                    if (getRunSate() == DownloadTask.SATE_RUN) {
                        onSuccess();
                    }
                } else {
                    setError(new RuntimeException("responseCode=" + response.code()));
                }

            } catch (IOException e) {
                e.printStackTrace();
                setError(e);
            } finally {
                CloseableUtil.closeQuietly(randomAccessFile);
                CloseableUtil.closeQuietly(inputStream);
            }


        }
    }
}
